﻿using System;
using System.Collections.Generic;
using System.Linq;
using CLM.Gestao.Interfaces;
using CLM.Gestao.Administrador.DAL;

namespace CLM.Gestao.Administrador.BLL
{
    public class PerfilAcesso : PerfilAcessoBLO<TB_PERFIL_ACESSO>
    {
        #region Propriedades

        public int IdPerfilAcesso { get; set; }
        public string NomePerfilAcesso { get; set; }
        public bool? ManutencaoUsuario { get; set; }
        public bool? ManutencaoPerfilAcesso { get; set; }
        public bool? ManutencaoPeriodo { get; set; }
        public bool? SincronizaCentroCusto { get; set; }
        public bool? ManutencaoCentroCusto { get; set; }
        public bool? SincronizaContaContabil { get; set; }
        public bool? ManutencaoContaContabil { get; set; }
        public bool? SincronizaProdutos { get; set; }
        public bool? ImportacaoProdutoGlobal { get; set; }
        public bool? ManutencaoProdutos { get; set; }
        public bool? RelatorioDivergenciaProdutos { get; set; }
        public bool? ImportaCustoUnitarioProduto { get; set; }
        public bool? ImportaCustoUnitarioAmostra { get; set; }
        public bool? SincronizaVendaRealizada { get; set; }
        public bool? ImportacaoProvisoesDevolucao { get; set; }
        public bool? RelatorioIndicadoresVenda { get; set; }
        public bool? PremissasCalculoCusto { get; set; }
        public bool? ImportacaoCusto { get; set; }
        public bool? SincronizarDespesasRealizadas { get; set; }
        public bool? RelatorioIndicadoresDespesas { get; set; }
        public bool? AlocacaoDespesas { get; set; }
        public bool? ImportarRateioGGF { get; set; }
        public bool? ImportarPromocaoGrade { get; set; }
        public bool? CalcularRateioProduto { get; set; }
        public bool? VisualizarPNL { get; set; }
        public bool? ExportarVendas { get; set; }
        public bool? ExportarCustosDespesas { get; set; }

        #endregion Propriedades

        #region Conversões

        private List<TB_PERFIL_ACESSO> ConvertToEDM(List<Lista> pLista)
        {
            List<TB_PERFIL_ACESSO> List = (from p in pLista
                                           select new TB_PERFIL_ACESSO
                                           {
                                               ID_PERFIL_ACESSO = p.IdPerfilAcesso,
                                               NOME_PERFIL_ACESSO = p.NomePerfilAcesso,
                                               ABRE_CADASTROS = p.AlocacaoDespesas,
                                               ABRE_CONCILIACAO = p.CalcularRateioProduto,
                                               ABRE_CONTROLADORIA = p.ExportarCustosDespesas,
                                               ABRE_JUSTIFICATIVA = p.ExportarVendas,
                                               ABRE_PAINEL = p.ImportacaoCusto,
                                               ABRE_PERFIL_ACESSO = p.ImportacaoProdutoGlobal,
                                               ABRE_SUMARIO_EXECUTIVO = p.ImportacaoProvisoesDevolucao,
                                               ABRE_SUMARIO_FOPAG = p.ImportaCustoUnitarioAmostra,
                                               ABRE_SUMARIO_PROJETO = p.ImportaCustoUnitarioProduto,
                                               DIFERE_ORCAMENTO = p.ImportarPromocaoGrade,
                                               EDITA_WORKFLOW = p.ImportarRateioGGF,
                                               EFETUA_CALCULOS = p.ManutencaoCentroCusto,
                                               FOPAG_NO_SUM_COMPLETO = p.ManutencaoContaContabil,
                                               GERA_BSC = p.ManutencaoPerfilAcesso,
                                               HISTORICO_PROJETOS = p.ManutencaoPeriodo,
                                               IMPORTA_ARQUIVOS = p.ManutencaoProdutos,
                                               IMPORTA_CENTROCUSTO = p.ManutencaoUsuario,
                                               IMPORTA_DESPESAS_COMPROMETIDAS = p.PremissasCalculoCusto,
                                               IMPORTA_HISTORICO = p.RelatorioDivergenciaProdutos,
                                               IMPORTA_LANCAMENTOS = p.RelatorioIndicadoresDespesas,
                                               IMPORTA_ORCAMENTO = p.RelatorioIndicadoresVenda,
                                               IMPORTA_PERIODO_FECHADO = p.SincronizaCentroCusto,
                                               IMPORTA_PRODUTO = p.SincronizaContaContabil,
                                               INDICA_ACESSA_SISTEMA = p.SincronizaProdutos,
                                               INDICA_APROVACAO_ORCAMENTO = p.SincronizarDespesasRealizadas,
                                               INDICA_APROVACAO_QUADRO_FUNCIONARIO = p.SincronizaVendaRealizada,
                                               INDICA_IMPORTACAO_FUNCIONARIOS = p.VisualizarPNL 
                                           }).ToList();
            return List;
        }

        private List<Lista> ConvertToContext(IQueryable<TB_PERFIL_ACESSO> pContext)
        {
            List<Lista> List = (from p in pContext
                                select new Lista
                                         {
                                             IdPerfilAcesso = p.ID_PERFIL_ACESSO,
                                             NomePerfilAcesso = p.NOME_PERFIL_ACESSO,
                                             AlocacaoDespesas = p.ABRE_CADASTROS,
                                             CalcularRateioProduto = p.ABRE_CONCILIACAO,
                                             ExportarCustosDespesas = p.ABRE_CONTROLADORIA,
                                             ExportarVendas = p.ABRE_JUSTIFICATIVA,
                                             ImportacaoCusto = p.ABRE_PAINEL,
                                             ImportacaoProdutoGlobal = p.ABRE_PERFIL_ACESSO,
                                             ImportacaoProvisoesDevolucao = p.ABRE_SUMARIO_EXECUTIVO,
                                             ImportaCustoUnitarioAmostra = p.ABRE_SUMARIO_FOPAG,
                                             ImportaCustoUnitarioProduto = p.ABRE_SUMARIO_PROJETO,
                                             ImportarPromocaoGrade = p.DIFERE_ORCAMENTO,
                                             ImportarRateioGGF = p.EDITA_WORKFLOW,
                                             ManutencaoCentroCusto = p.EFETUA_CALCULOS,
                                             ManutencaoContaContabil = p.FOPAG_NO_SUM_COMPLETO,
                                             ManutencaoPerfilAcesso = p.GERA_BSC,
                                             ManutencaoPeriodo = p.HISTORICO_PROJETOS,
                                             ManutencaoProdutos = p.IMPORTA_ARQUIVOS,
                                             ManutencaoUsuario = p.IMPORTA_CENTROCUSTO,
                                             PremissasCalculoCusto = p.IMPORTA_DESPESAS_COMPROMETIDAS,
                                             RelatorioDivergenciaProdutos = p.IMPORTA_HISTORICO,
                                             RelatorioIndicadoresDespesas = p.IMPORTA_LANCAMENTOS,
                                             RelatorioIndicadoresVenda = p.IMPORTA_ORCAMENTO,
                                             SincronizaCentroCusto = p.IMPORTA_PERIODO_FECHADO,
                                             SincronizaContaContabil = p.IMPORTA_PRODUTO,
                                             SincronizaProdutos = p.INDICA_ACESSA_SISTEMA,
                                             SincronizarDespesasRealizadas = p.INDICA_APROVACAO_ORCAMENTO,
                                             SincronizaVendaRealizada = p.INDICA_APROVACAO_QUADRO_FUNCIONARIO,
                                             VisualizarPNL = p.INDICA_IMPORTACAO_FUNCIONARIOS
                                         }).ToList();
            return List;
        }

        #endregion Conversões

        #region CRUD
        /// <summary>
        /// 
        /// </summary>
        /// <param name="pLista"></param>
        public void Add(List<Lista> pLista)
        {
            try
            {
                foreach (var item in ConvertToEDM(pLista))
                    base.Add(item);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pLista"></param>
        public void Delete(List<Lista> pLista)
        {
            try
            {
                foreach (var item in ConvertToEDM(pLista))
                    base.Delete(item);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pLista"></param>
        public void Update(List<Lista> pLista)
        {
            try
            {
                foreach (var item in ConvertToEDM(pLista))
                    base.Update(item);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// Efetua a pesquisa na tabela, filtrando as solicitações do usuário
        /// </summary>
        /// <param name="pPesquisa">pPesquisa</param>
        /// <returns>Lista</returns>
        private IQueryable<TB_PERFIL_ACESSO> Get(Lista pPesquisa)
        {
            IQueryable<TB_PERFIL_ACESSO> Consulta;

            Consulta = from p in GetAll()
                       select p;
            if (pPesquisa != null)
            {
                if (!string.IsNullOrWhiteSpace(pPesquisa.NomePerfilAcesso))
                    Consulta = from p in Consulta where p.NOME_PERFIL_ACESSO.Contains(pPesquisa.NomePerfilAcesso) select p;

                if (pPesquisa.IdPerfilAcesso > 0)
                    Consulta = from p in Consulta where p.ID_PERFIL_ACESSO == pPesquisa.IdPerfilAcesso select p;

            }
            return Consulta;
        }

        #endregion CRUD

        #region Retorna Listas e Itens

        public List<Lista> GetLista()
        {
            return GetLista(new Lista());
        }

        public List<Lista> GetLista(Lista pPesquisa)
        {
            var ListaPerfilAcesso = ConvertToContext(Get(pPesquisa));
            return ListaPerfilAcesso;
        }

        public List<Itens> GetItens()
        {
            return GetItens(new Lista());
        }

        public List<Itens> GetItens(Lista pPesquisa)
        {
            List<Itens> ListaPerfilAcesso = (from p in Get(pPesquisa)
                                        select new Itens()
                                        {
                                            IdPerfilAcesso = p.ID_PERFIL_ACESSO,
                                            NomePerfilAcesso = p.NOME_PERFIL_ACESSO
                                        }).ToList();
            return ListaPerfilAcesso;
        }

        #endregion Retorna Listas e Itens

        #region Consultas

        #endregion Consultas

        #region Classes

        /// <summary>
        /// 
        /// </summary>
        public class Itens
        {
            public int IdPerfilAcesso { get; set; }
            public string NomePerfilAcesso { get; set; }
        }

        /// <summary>
        /// 
        /// </summary>
        public class Lista
        {
            public int IdPerfilAcesso { get; set; }
            public string NomePerfilAcesso { get; set; }
            public bool? ManutencaoUsuario { get; set; }
            public bool? ManutencaoPerfilAcesso { get; set; }
            public bool? ManutencaoPeriodo { get; set; }
            public bool? ManutencaoCentroCusto { get; set; }
            public bool? SincronizaCentroCusto { get; set; }
            public bool? ManutencaoContaContabil { get; set; }
            public bool? SincronizaContaContabil { get; set; }
            public bool? SincronizaProdutos { get; set; }
            public bool? ImportacaoProdutoGlobal { get; set; }
            public bool? ManutencaoProdutos { get; set; }
            public bool? RelatorioDivergenciaProdutos { get; set; }
            public bool? ImportaCustoUnitarioProduto { get; set; }
            public bool? ImportaCustoUnitarioAmostra { get; set; }
            public bool? SincronizaVendaRealizada { get; set; }
            public bool? ImportacaoProvisoesDevolucao { get; set; }
            public bool? RelatorioIndicadoresVenda { get; set; }
            public bool? PremissasCalculoCusto { get; set; }
            public bool? ImportacaoCusto { get; set; }
            public bool? SincronizarDespesasRealizadas { get; set; }
            public bool? RelatorioIndicadoresDespesas { get; set; }
            public bool? AlocacaoDespesas { get; set; }
            public bool? ImportarRateioGGF { get; set; }
            public bool? ImportarPromocaoGrade { get; set; }
            public bool? CalcularRateioProduto { get; set; }
            public bool? VisualizarPNL { get; set; }
            public bool? ExportarVendas { get; set; }
            public bool? ExportarCustosDespesas { get; set; }
        }

        #endregion Classes
    }

    public class PerfilAcessoBLO<T> : IBLO<T> where T : TB_PERFIL_ACESSO
    {
        /// <summary>
        /// 
        /// </summary>
        private PerfilAcessoDAO<T> _base = new PerfilAcessoDAO<T>();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pEntity"></param>
        /// <returns></returns>
        public T Add(T pEntity)
        {
            Validate(pEntity);
            _base.Add(pEntity);
            return _base.Save(pEntity);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pEntity"></param>
        /// <returns></returns>
        public T Save(T pEntity)
        {
            Validate(pEntity);
            return _base.Save(pEntity);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pEntity"></param>
        public void Delete(T pEntity)
        {
            ValidateDelete(pEntity);
            _base.Delete(pEntity);
            _base.Save(pEntity);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pEntity"></param>
        /// <returns></returns>
        public T Update(T pEntity)
        {
            Validate(pEntity);
            _base.Update(pEntity);
            return _base.Save(pEntity);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public IQueryable<T> GetAll()
        {
            return _base.GetAll();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pEntity"></param>
        public void Validate(T pEntity)
        {
            int Perfilvalidate = (from u in _base.GetAll()
                                where (u.NOME_PERFIL_ACESSO == pEntity.NOME_PERFIL_ACESSO  && u.ID_PERFIL_ACESSO != pEntity.ID_PERFIL_ACESSO)
                                select u).Count();

            if (Perfilvalidate > 0)
                throw new Exception("Já existe um perfil de acesso cadastrado com esse nome.");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pEntity"></param>
        public void ValidateDelete(T pEntity)
        {
            int Perfilvalidate = (from u in _base.GetAll()
                                  where u.TB_USUARIO.Where(w => w.ID_PERFIL_ACESSO == pEntity.ID_PERFIL_ACESSO).Select(s => s).Count() > 0
                                  select u).Count();

            if (Perfilvalidate > 0)
                throw new Exception("Existem usuários relacionados com este perfil de acesso.\nA operação não pôde ser concluída");
        }
    }
}